<template>
  <canvas type="2d" v-if="isUseNewCanvas" class="ec-canvas" :canvas-id="canvasId" @init="init" @touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd"> </canvas>
  <canvas v-else class="ec-canvas" :canvas-id="canvasId" @init="init" @touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd"> </canvas>
</template>

<script>
import WxCanvas from './wx-canvas'
import * as echarts from './echarts'

let ctx

function wrapTouch(event) {
  for (let i = 0; i < event.touches.length; ++i) {
    const touch = event.touches[i]
    touch.offsetX = touch.x
    touch.offsetY = touch.y
  }
  return event
}

export default {
  props: {
    canvasId: {
      type: String,
      default: () => {
        return 'ec-canvas'
      }
    },
    ec: {
      type: Object
    },
    forceUseOldCanvas: {
      type: Boolean,
      value: false
    }
  },
  data() {
    return {
      $curChart: {},
      toHandleList: [],
      isUseNewCanvas: true
    }
  },
  watch: {
    'ec.option': {
      deep: true,
      handler(val, oldVal) {
        this.setOption(val)
      }
    }
  },
  onReady: function () {
    if (!this.ec) {
      console.warn('组件需绑定 ec 变量，例：<ec-canvas id="mychart-dom-bar" ' + 'canvas-id="mychart-bar" ec="{{ ec }}"></ec-canvas>')
      return
    }
    if (!this.ec.lazyLoad) {
      this.init()
    }
  },
  methods: {
    compareVersion(v1, v2) {
      v1 = v1.split('.')
      v2 = v2.split('.')
      const len = Math.max(v1.length, v2.length)

      while (v1.length < len) {
        v1.push('0')
      }
      while (v2.length < len) {
        v2.push('0')
      }

      for (let i = 0; i < len; i++) {
        const num1 = parseInt(v1[i])
        const num2 = parseInt(v2[i])

        if (num1 > num2) {
          return 1
        } else if (num1 < num2) {
          return -1
        }
      }
      return 0
    },
    init(callback) {
      const version = wx.getSystemInfoSync().SDKVersion

      let canUseNewCanvas = this.compareVersion(version, '2.9.0') >= 0
      if (this.forceUseOldCanvas) {
        if (canUseNewCanvas) console.warn('开发者强制使用旧canvas,建议关闭')
        canUseNewCanvas = false
      }
      this.isUseNewCanvas = canUseNewCanvas && !this.forceUseOldCanvas
      if (this.isUseNewCanvas) {
        console.log('微信基础库版本大于2.9.0，开始使用<canvas type="2d"/>')
        // 2.9.0 可以使用 <canvas type="2d"></canvas>
        this.initByNewWay(callback)
      } else {
        const isValid = this.compareVersion(version, '1.9.91') >= 0
        if (!isValid) {
          console.error('微信基础库版本过低，需大于等于 1.9.91。' + '参见：https://github.com/ecomfe/echarts-for-weixin' + '#%E5%BE%AE%E4%BF%A1%E7%89%88%E6%9C%AC%E8%A6%81%E6%B1%82')
          return
        } else {
          console.warn('建议将微信基础库调整大于等于2.9.0版本。升级后绘图将有更好性能')
          this.initByOldWay(callback)
        }
      }
    },
    initByOldWay(callback) {
      // 1.9.91 <= version < 2.9.0：原来的方式初始化
      ctx = wx.createCanvasContext(this.canvasId, this)
      const canvas = new WxCanvas(ctx, this.canvasId, false)
      const that = this
      echarts.setCanvasCreator(() => {
        return canvas
      })
      // const canvasDpr = wx.getSystemInfoSync().pixelRatio // 微信旧的canvas不能传入dpr
      const canvasDpr = 1
      var query = wx.createSelectorQuery().in(this)
      query
        .select('.ec-canvas')
        .boundingClientRect((res) => {
          if (typeof callback === 'function') {
            that.$curChart = callback(canvas, res.width, res.height, canvasDpr)
          } else if (that.ec) {
            that.$curChart = that.initChart(canvas, res.width, res.height, canvasDpr)
          } else {
            that.triggerEvent('init', {
              canvas: canvas,
              width: res.width,
              height: res.height,
              devicePixelRatio: canvasDpr // 增加了dpr，可方便外面echarts.init
            })
          }
        })
        .exec()
    },
    initByNewWay(callback) {
      const that = this
      // version >= 2.9.0：使用新的方式初始化
      const query = wx.createSelectorQuery().in(this)
      query
        .select('.ec-canvas')
        .fields({
          node: true,
          size: true
        })
        .exec((res) => {
          const canvasNode = res[0].node

          const canvasDpr = wx.getSystemInfoSync().pixelRatio
          const canvasWidth = res[0].width
          const canvasHeight = res[0].height

          const ctx = canvasNode.getContext('2d')

          const canvas = new WxCanvas(ctx, that.canvasId, true, canvasNode)
          echarts.setCanvasCreator(() => {
            return canvas
          })

          if (typeof callback === 'function') {
            that.$curChart = callback(canvas, canvasWidth, canvasHeight, canvasDpr)
          } else if (that.ec) {
            that.$curChart = that.initChart(canvas, canvasWidth, canvasHeight, canvasDpr)
          } else {
            that.triggerEvent('init', {
              canvas: canvas,
              width: canvasWidth,
              height: canvasHeight,
              devicePixelRatio: canvasDpr
            })
          }
        })
    },
    setOption(val) {
      if (!this.$curChart || !this.$curChart.setOption) {
        this.toHandleList.push(val)
      } else {
        this.$curChart.setOption(val)
      }
    },
    canvasToTempFilePath(opt) {
      if (this.isUseNewCanvas) {
        // 新版
        const query = wx.createSelectorQuery().in(this)
        query
          .select('.ec-canvas')
          .fields({
            node: true,
            size: true
          })
          .exec((res) => {
            const canvasNode = res[0].node
            opt.canvas = canvasNode
            wx.canvasToTempFilePath(opt)
          })
      } else {
        // 旧的
        if (!opt.canvasId) {
          opt.canvasId = this.canvasId
        }
        ctx.draw(true, () => {
          wx.canvasToTempFilePath(opt, this)
        })
      }
    },

    touchStart(e) {
      if (this.ec.stopTouchEvent) {
        e.preventDefault()
        e.stopPropagation()
        return
      }
      this.$emit('touchstart', e)
      if (this.$curChart && e.touches.length > 0) {
        var touch = e.touches[0]
        var handler = this.$curChart.getZr().handler
        if (handler) {
          handler.dispatch('mousedown', {
            zrX: touch.x,
            zrY: touch.y
          })
          handler.dispatch('mousemove', {
            zrX: touch.x,
            zrY: touch.y
          })
          handler.processGesture(wrapTouch(e), 'start')
        }
      }
    },

    touchMove(e) {
      if (this.ec.stopTouchEvent) {
        e.preventDefault()
        e.stopPropagation()
        return
      }
      this.$emit('touchmove', e)
      if (this.$curChart && e.touches.length > 0) {
        var touch = e.touches[0]
        var handler = this.$curChart.getZr().handler
        if (handler) {
          handler.dispatch('mousemove', {
            zrX: touch.x,
            zrY: touch.y
          })
          handler.processGesture(wrapTouch(e), 'change')
        }
      }
    },

    touchEnd(e) {
      if (this.ec.stopTouchEvent) {
        e.preventDefault()
        e.stopPropagation()
        return
      }
      this.$emit('touchend', e)
      if (this.$curChart) {
        const touch = e.changedTouches ? e.changedTouches[0] : {}
        var handler = this.$curChart.getZr().handler
        if (handler) {
          handler.dispatch('mouseup', {
            zrX: touch.x,
            zrY: touch.y
          })
          handler.dispatch('click', {
            zrX: touch.x,
            zrY: touch.y
          })
          handler.processGesture(wrapTouch(e), 'end')
        }
      }
    },

    initChart(canvas, width, height, canvasDpr) {
      this.$curChart = echarts.init(canvas, null, {
        width: width,
        height: height,
        devicePixelRatio: canvasDpr
      })
      canvas.setChart(this.$curChart)
      this.$curChart.setOption(this.ec.option)
      this.$emit('inited', this.$curChart)
      return this.$curChart
    }
  }
}
</script>

<style lang="scss">
.ec-canvas {
  width: 100%;
  height: 100%;
  display: block;
}
</style>
